import React, { useEffect, useState, useMemo } from 'react';
import { Cascader, message } from 'antd';
import { getLocale } from 'umi';
import { useDeepCompareEffect } from 'react-use'
import { cloneDeep } from 'lodash'
import { getTreeNodePath, disableNodes, autoTransformLocaleValue, isChineseLanguage } from './utils';
import areaData from './area.js';

/**
 * 组件说明：区域选择器
 * CityPicker 支持多种传值方式、支持多语言（area.json仅支持中文跟英文）
 * 1. valueType="array" value=['中国','福建省','厦门市'] 返回值 ['中国','福建省','厦门市']
 * 2. valueType="code" value="350200000000" 返回值 "350200000000"
 * 3. valueType="formatted" format="/" value="中国/福建省/厦门市" 返回值 "中国/福建省/厦门市"
 * 4. valueType="codeArray" value=["39","350000000000","350200000000","350203000000"] 返回值 ["39","350000000000","350200000000","350203000000"]
 */
const CityPicker = React.forwardRef(
    (
        {
            valueType = 'array',
            value,
            onChange,
            format,
            showSearch = false,
            disabledArea = [],
            filterAreaFn,
            showOnly,
            ...otherprops
        },
        ref
    ) => {
        const [area, setArea] = useState([]);
        const [isChinese, setIsChinese] = useState(true);
        const [initialValue, setInitialValue] = useState([]);

        // 懒加载省市区json 文件
        useDeepCompareEffect(() => {
            const asyncImportCity = async () => {
                try {
                    // const { default: areaData } = await import(/* webpackChunkName: "areaData" */ './area.json');
                    let result = cloneDeep(areaData);
                    if (disabledArea.length) {
                        result = disableNodes(result, disabledArea, 'code', 'children');
                    }
                    if (filterAreaFn && filterAreaFn instanceof Function) {
                        result = filterAreaFn(result)
                    }
                    setArea(result);
                } catch (e) {
                    message.error('获取城市数据失败！');
                    setArea([]);
                }
            };

            asyncImportCity();
        }, [disabledArea]);

        // React.useEffect(() => {
        //     // setLocale('en-US');
        //     setLocale('zh-CN');
        // }, []);

        // 语言环境检测
        useEffect(() => {
            const regex = /zh[-_]cn/gi;
            const userLanguage = getLocale();

            // 判断是否为中文
            if (regex.test(userLanguage)) {
                setIsChinese(true);
            } else {
                setIsChinese(false);
            }
        }, []);

        // 对不同类型的值进行格式化，最终格式化为数组形式
        useEffect(() => {
            // 多语言处理
            const transformValue = (city = []) => {
                if (Array.isArray(city)) {
                    const valueIsChinese = isChineseLanguage(city[0]);
                    if (valueIsChinese && isChinese) {
                        return city;
                    }

                    return autoTransformLocaleValue(
                        area,
                        city,
                        valueIsChinese ? 'nameZh' : 'nameEn',
                        'children',
                        isChinese ? 'nameZh' : 'nameEn'
                    );
                }
                return [];
            };

            if (value) {
                switch (valueType) {
                    case 'array': {
                        setInitialValue(transformValue(value));
                        // setInitialValue(Array.isArray(value) ? value : []);
                        break;
                    }
                    case 'code': {
                        const result = getTreeNodePath(area, value, 'code', 'children') || [];
                        setInitialValue(result.map(node => (isChinese ? node.nameZh : node.nameEn)));
                        break;
                    }
                    case 'formatted': {
                        if (format && typeof value === 'string') {
                            setInitialValue(transformValue(value.split(format)));
                        } else {
                            setInitialValue([]);
                        }
                        // setInitialValue(format && typeof value === 'string' ? value.split(format) : []);
                        break;
                    }
                    case 'codeArray': {
                        let result = [];
                        if (Array.isArray(value) && value?.length) {
                            result =
                                getTreeNodePath(
                                    area,
                                    value.length > 1 ? value[value.length - 1] : value[0],
                                    'code',
                                    'children'
                                ) || [];
                        }
                        setInitialValue(result.map(node => (isChinese ? node.nameZh : node.nameEn)));
                        break;
                    }
                    default:
                        setInitialValue([]);
                        break;
                }
            }
        }, [area, format, isChinese, value, valueType]);

        // 设置默认的筛选条件，兼容多语言
        const initialShowSearch = useMemo(() => {
            // const areaField = isChinese ? 'nameZh' : 'nameEn';
            const filter = (inputValue, path) =>
                path.some(
                    option =>
                        option.nameZh.toLowerCase().indexOf(inputValue.toLowerCase()) > -1 ||
                        option.nameEn.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
                );
            if (typeof showSearch === 'boolean' && showSearch) {
                return {
                    filter
                };
            }
            return showSearch;
        }, [isChinese, showSearch]);

        const initialShowOnlyValue = useMemo(() => {
            if (showOnly && initialValue.length) {
                return initialValue.join(format || '/');
            }

            return '';
        }, [initialValue, showOnly, format]);

        // 解析为传入的类型数据
        const handleChanged = (_value, selectedOptions = []) => {
            const selectedValue = selectedOptions.map(item => (isChinese ? item.nameZh : item.nameEn));
            if (onChange) {
                switch (valueType) {
                    case 'array': {
                        onChange(selectedValue, selectedOptions);
                        break;
                    }
                    case 'code': {
                        onChange(
                            selectedOptions.length ? selectedOptions[selectedOptions.length - 1].code : '',
                            selectedOptions
                        );
                        break;
                    }
                    case 'formatted': {
                        onChange(selectedValue.join(format), selectedOptions);
                        break;
                    }
                    case 'codeArray': {
                        onChange(
                            selectedOptions.map(item => item.code),
                            selectedOptions
                        );
                        break;
                    }
                    default:
                        break;
                }
            }
            setInitialValue(selectedValue);
        };

        return (
            <div ref={ref}>
                {showOnly ? (
                    <div>{initialShowOnlyValue}</div>
                ) : (
                    <Cascader
                        fieldNames={{
                            id: 'code',
                            label: isChinese ? 'nameZh' : 'nameEn',
                            value: isChinese ? 'nameZh' : 'nameEn'
                        }}
                        showSearch={initialShowSearch}
                        changeOnSelect
                        options={area}
                        value={initialValue}
                        onChange={handleChanged}
                        {...otherprops}
                    />
                )}
            </div>
        );
    }
);

export default CityPicker;
